using Abp.Application.Services.Dto;
using Abp.Domain.Entities.Auditing;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yozeev.BusinessLogic;
using Yozeev.BusinessLogic.Stats.Dtos;
using Yozeev.Common;
using Yozeev.Controllers.Stats.Filters;
using Yozeev.Dtos;
using Yozeev.SystemConfig;
using Yozeev.UserManagerment.Users;

namespace Yozeev.Controllers.Stats
{
    /// <summary>
    /// 销售员售票统计
    /// </summary>
    [Route("api/Stats/[Controller]/[Action]")]
    public class SellerTicketController : YozeevControllerBase
    {
        private readonly IRepository<Activity, Guid> _activityRepository;

        private readonly IRepository<User, long> _userRepository;

        private readonly IRepository<PayMethod, Guid> _payMethodRepository;

        private readonly IRepository<TicketDetail, Guid> _ticketDetailRep;

        private readonly IRepository<Ticket, Guid> _ticketRep;

        private readonly IRepository<TicketPrice, Guid> _ticketPriceRep;

        private readonly IRepository<ActivityDetail, Guid> _activityDetail;

        private readonly IRepository<Boat, Guid> _boatRep;

        private readonly IRepository<Schedule, Guid> _scheduleRep;

        private readonly AbstractFilter _salerFilter;

        private readonly AbstractFilter _boatFilter;

        private readonly AbstractFilter _ticketTypeFilter;

        private readonly AbstractFilter _routeFilter;

        private readonly IQueryHelper _queryHelper;

        public SellerTicketController(
            IRepository<Activity, Guid> activityRepository,
            IRepository<User, long> userRepository,
            IRepository<PayMethod, Guid> payMethodRepository,
            IRepository<User, long> userRep,
            IRepository<TicketDetail, Guid> ticketDetailRep,
            IRepository<Ticket, Guid> ticketRep,
            IRepository<Boat, Guid> boatRep,
            IRepository<Schedule, Guid> scheduleRep,
            IRepository<TicketPrice, Guid> ticketPriceRep,
            IRepository<ActivityDetail, Guid> activityDetail,
            SalerFilter salerFilter,
            BoatFilter boatFilter,
            TicketTypeFilter ticketTypeFilter,
            RouteFilter routeFilter,
            IQueryHelper queryHelper)
        {
            _ticketDetailRep = ticketDetailRep;
            _ticketRep = ticketRep;
            _activityRepository = activityRepository;
            _userRepository = userRepository;
            _payMethodRepository = payMethodRepository;
            _scheduleRep = scheduleRep;
            _boatRep = boatRep;
            _ticketPriceRep = ticketPriceRep;
            _activityDetail = activityDetail;
            _salerFilter = salerFilter;
            _boatFilter = boatFilter;
            _ticketTypeFilter = ticketTypeFilter;
            _routeFilter = routeFilter;
            _queryHelper = queryHelper;
        }

        /// <summary>
        /// 售票员售票统计
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<StatsPagedResultDto<SellerTicketResultDto>> GetPaged(SellerTicketInput input, string boatId, string ticketId)
        {
            var users = _userRepository.GetAll();
            var userIds = users.Select(u => u.Id).ToList();
            var paymethods = _payMethodRepository.GetAll();
            var activities = _activityRepository.GetAll()
                .Where(a => userIds.Contains((long)a.CreatorUserId))
                .Where(_queryHelper.WhereExp<Activity>(input.queryData));
            if (!string.IsNullOrEmpty(boatId))
            {
                var scheduleIds = _scheduleRep.GetAll().Where(s => s.BoatId.ToString()
                .Equals(boatId)).Select(s => s.Id).ToList();
                activities = activities.Where(a => scheduleIds.Contains(a.ScheduleId.Value));
            }

            if (!string.IsNullOrEmpty(ticketId))
            {
                var ticketPriceIds = _ticketPriceRep.GetAll()
                    .Where(t => t.TicketId.ToString().Equals(ticketId)).Select(t => t.Id).ToList();
                var activityIds = _activityDetail.GetAll()
                    .Where(a => ticketPriceIds.Contains(a.TicketPriceId))
                    .Select(a => a.ActivityId)
                    .ToList();
                activities = activities.Where(a => activityIds.Contains(a.Id));
            }

            var tmp1 = from activity in activities
                       where activity.PayStatus == PayStatusEnum.PayStatusPayment || activity.PayStatus == PayStatusEnum.PayStatusRefund
                       join paymethod in paymethods
                       on activity.PayMethod equals paymethod
                       group activity by new { activity.CreatorUser, activity.PayMethod } into a
                       select new
                       {
                           CreatorUserId = a.Key.CreatorUser.Id,
                           //售票金额
                           CashSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           WeiChatSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           CardSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           ZhiFuBaoSaleAmount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalAmount : 0) : 0),
                           //退票金额
                           CashRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           WeiChatRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           CardRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           ZhiFuBaoRefundAmount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalAmount : 0) : 0),
                           //售票数量
                           CashSaleCount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalQuantity : 0) : 0),
                           WeiChatSaleCount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalQuantity : 0) : 0),
                           CardSaleCount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalQuantity : 0) : 0),
                           ZhiFuBaoSaleCount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypePayment ? ac.TotalQuantity : 0) : 0),
                           //退票数量
                           CashRefundCount = a.Sum(ac => ac.PayMethod.PayCode == "Cash" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalQuantity : 0) : 0),
                           WeiChatRefundCount = a.Sum(ac => ac.PayMethod.PayCode == "WeiChat" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalQuantity : 0) : 0),
                           CardRefundCount = a.Sum(ac => ac.PayMethod.PayCode == "Card" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalQuantity : 0) : 0),
                           ZhiFuBaoRefundCount = a.Sum(ac => ac.PayMethod.PayCode == "ZhiFuBao" ? (ac.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? ac.TotalQuantity : 0) : 0)
                       };
            //计算小计
            var tmp2 = from tmp in tmp1
                       group tmp by tmp into g
                       select new SellerTicketResultDto
                       {
                           Saler = (from user in users where user.Id == g.Key.CreatorUserId select user).FirstOrDefault(),
                           CashSaleAmount = g.Key.CashSaleAmount,
                           WeiChatSaleAmount = g.Key.WeiChatSaleAmount,
                           CardSaleAmount = g.Key.CardSaleAmount,
                           ZhiFuBaoSaleAmount = g.Key.ZhiFuBaoSaleAmount,
                           //退票金额
                           CashRefundAmount = g.Key.CashRefundAmount,
                           WeiChatRefundAmount = g.Key.WeiChatRefundAmount,
                           CardRefundAmount = g.Key.CardRefundAmount,
                           ZhiFuBaoRefundAmount = g.Key.ZhiFuBaoRefundAmount,
                           //售票数量
                           CashSaleCount = g.Key.CashSaleCount,
                           WeiChatSaleCount = g.Key.WeiChatSaleCount,
                           CardSaleCount = g.Key.CardSaleCount,
                           ZhiFuBaoSaleCount = g.Key.ZhiFuBaoSaleCount,
                           //退票数量
                           CashRefundCount = g.Key.CashRefundCount,
                           WeiChatRefundCount = g.Key.WeiChatRefundCount,
                           CardRefundCount = g.Key.CardRefundCount,
                           ZhiFuBaoRefundCount = g.Key.ZhiFuBaoRefundCount,
                           //小结
                           CashTotalAmount = g.Key.CashSaleAmount - g.Key.CashRefundAmount,
                           CashTotalCount = g.Key.CashSaleCount - g.Key.CashRefundCount,
                           WeiChatTotalAmount = g.Key.WeiChatSaleAmount - g.Key.WeiChatRefundAmount,
                           WeiChatTotalCount = g.Key.WeiChatSaleCount - g.Key.WeiChatRefundCount,
                           CardTotalAmount = g.Key.CardSaleAmount - g.Key.CardRefundAmount,
                           CardTotalCount = g.Key.CardSaleCount - g.Key.CardRefundCount,
                           ZhiFuBaoTotalCount = g.Key.ZhiFuBaoSaleCount - g.Key.ZhiFuBaoRefundCount,
                           ZhiFuBaoTotalAmount = g.Key.ZhiFuBaoSaleAmount - g.Key.ZhiFuBaoRefundAmount
                       };
            var count = await tmp2.CountAsync();
            var result = await tmp2.ToListAsync();
            Dictionary<string, IEnumerable<object>> filters = new Dictionary<string, IEnumerable<object>>();
            _salerFilter.Decorate(filters);
            _boatFilter.Decorate(filters);
            _ticketTypeFilter.Decorate(filters);
            _routeFilter.Decorate(filters);

            return new StatsPagedResultDto<SellerTicketResultDto>(count, result.AsQueryable().PageBy(input).ToList(), filters);
        }

        /// <summary>
        /// 销售员售票统计——详情
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<StatsPagedResultDto<ScheduleTicketDetailResultDto>> SellerTicketDetailStat(string userId)
        {
            var ticketDetails = _ticketDetailRep.GetAll().Where(s => s.CreatorUserId.ToString() == userId);
            var tickets = _ticketRep.GetAll();

            var result = from ticketDetail in ticketDetails
                         select new ScheduleTicketDetailResultDto
                         {
                             Ticket = (from ticket in tickets
                                       where ticket.Id == ticketDetail.TicketId
                                       select ticket).FirstOrDefault(),
                             Schedule = ticketDetail.Schedule,
                             Customer = ticketDetail.Customer,
                             TicketDetail = ticketDetail
                         };

            var count = result.Count();
            return new StatsPagedResultDto<ScheduleTicketDetailResultDto>(count, result.ToList());
        }
    }
}
